/*
	Copyright (c) 2010 Canadensys
*/
package net.canadensys.dataportal.vascan.utils;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.logging.Logger;

import net.canadensys.dataportal.utils.HibernateUtil;
import net.canadensys.dataportal.vascan.config.ApplicationConfig;
import net.canadensys.dataportal.vascan.config.impl.InstallationConfig;

import org.apache.commons.io.FileUtils;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Query;

/**
 * Class responsible to generate all the Vascan SiteMap.
 */
public class SiteMap {
	
	/**
	 * This function is used to generate a SiteMap.
	 * This function will overwrite the previous SiteMap files.
	 * @return
	 */
	public static final boolean build(){
		//if SiteMap is not wanted on this installation, return
		if(InstallationConfig.getInstance().get(InstallationConfig.SITE_MAP_DIR_KEY) == null){
			return true;
		}
		
		org.hibernate.Session hibernateSession = HibernateUtil.getSessionFactory().getCurrentSession();
		hibernateSession.beginTransaction();
		File taxonEn = new File(ApplicationConfig.getTaxonSiteMapFileEN());
		File taxonFr = new File(ApplicationConfig.getTaxonSiteMapFileFR());
		File vernacularEn = new File(ApplicationConfig.getVernacularSiteMapFileEN());
		File vernacularFr = new File(ApplicationConfig.getVernacularSiteMapFileFR());
		
		boolean success = true;
		try{
			Query query;
			
			//taxon ids
			query = hibernateSession.createSQLQuery("SELECT id from taxon")
					.addScalar("id",Hibernate.INTEGER);
			List<Integer> taxonIdList = query.list();
			
			//vernacular ids
			query = hibernateSession.createSQLQuery("SELECT id FROM vernacularname")
					.addScalar("id",Hibernate.INTEGER);
			List<Integer> vernacularIdList = query.list();
		
			success = success && writeToFile(taxonEn,taxonIdList, ApplicationConfig.getSiteMapURLTaxon(),null);
			success = success && writeToFile(vernacularEn,vernacularIdList, ApplicationConfig.getSiteMapURLVernacular(),null);
			success = success && writeToFile(taxonFr,taxonIdList, ApplicationConfig.getSiteMapURLTaxon(),ApplicationConfig.SITEMAP_LANG_PARAM_FR);
			success = success && writeToFile(vernacularFr,vernacularIdList, ApplicationConfig.getSiteMapURLVernacular(),ApplicationConfig.SITEMAP_LANG_PARAM_FR);
		
			hibernateSession.getTransaction().commit();
		}
		catch(HibernateException e){
			e.printStackTrace();
			success = false;
		}
		return success;
	}
	
	
	private static boolean writeToFile(File sitemap, List<Integer> idList, String idUrl, String lang){
		boolean isFileOk = true;
		PrintWriter pw = null;
		try {
			URI mainSite = new URI(InstallationConfig.getInstance().get(InstallationConfig.VASCAN_ROOT_URL_KEY));
			URI uri;
			
			pw = new PrintWriter(sitemap);
			String doc = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
			String openUrlset = "<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">";
			String closeUrlset = "</urlset>";
			pw.println(doc);
			pw.println(openUrlset);
			for(Integer currId : idList){
				uri = new URI(
						mainSite.getScheme(),
						mainSite.getHost(), 
						mainSite.getPath()+idUrl+currId,
						lang,
				        null);
				pw.println(content(uri.toASCIIString(),null));
				pw.flush();
			}
			pw.println(closeUrlset);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			isFileOk = false;
		} catch (URISyntaxException e) {
			e.printStackTrace();
			isFileOk = false;
		}
		finally{
			if(pw != null){
				pw.close();
			}
		}
		
		//do not leave incomplete file
		if(!isFileOk){
			sitemap.delete();
		}
		
		return isFileOk;
	}
	
	private static String content(String loc, String priority){
		StringBuilder results = new StringBuilder();
		results.append("<url>");
		results.append("<loc>").append(loc).append("</loc>");
		if(priority != null){
			results.append("<priority>").append(priority).append("</priority>");
		}
		results.append("</url>");
		return results.toString();
	}
	
	/**
	 * This function copies the SiteMap xml files to the deployed WebApp folder.
	 * If no SiteMapDir is defined, this function will just return.
	 */
	public static void copySiteMap(){
		String siteMapDir = InstallationConfig.getInstance().get(InstallationConfig.SITE_MAP_DIR_KEY);
		if(siteMapDir !=null){
			File siteMapFile= new File(siteMapDir);
			File deployedSiteMapRootFile = new File(InstallationConfig.getInstance().get(InstallationConfig.INSTALLATION_DIR_KEY));
			if(siteMapFile.exists()){
				for(File currFile : siteMapFile.listFiles()){
					try {
						FileUtils.copyFileToDirectory(currFile, deployedSiteMapRootFile);
					} catch (IOException e) {
						e.printStackTrace();
						Logger.getLogger(SiteMap.class.getName()).severe(e.getMessage());
					}
				}
			}
		}
	}
}